#if !defined(AFX_HTMLFORMAT_H__20000615_4D55_5A69_4ACA_0080AD509054__INCLUDED_)
#define AFX_HTMLFORMAT_H__20000615_4D55_5A69_4ACA_0080AD509054__INCLUDED_
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2000.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


class CHtmlFormat
{
public:
   static CString Format(LPCTSTR pstrText)
   {
      ATLASSERT(pstrText);
      if( pstrText==NULL ) return _T("");

      enum STATE { 
         STATE_INNERHTML, 
         STATE_SCRIPT, 
         STATE_TAG, 
         STATE_ATTRIB, 
         STATE_STRING, 
         STATE_COMMENT 
      } State;

      ATLTRACE("Text size before: %d\n", _tcslen(pstrText));

      CString s;
      DWORD dwSize = _tcslen(pstrText)*8;
      if( dwSize<4000 ) dwSize=8000;
      LPTSTR pstrTarget = s.GetBuffer(dwSize);
      LPTSTR pEnd = pstrTarget + dwSize - 256;
      LPTSTR pT = pstrTarget;

      TCHAR ch;
      TCHAR chString;
      State = STATE_INNERHTML;
      bool bIsScript = false;
      while( (ch = *pstrText++)!=_T('\0') ) {
         switch( ch ) {
         case _T('<'):
            if( State == STATE_SCRIPT ) {
               if( _tcsnicmp( pstrText, _T("/SCRIPT"), 7 )==0 ) {
                  State=STATE_INNERHTML;
                  *pT++ = _T('\\');
                  *pT++ = _T('c');
                  *pT++ = _T('f');
                  *pT++ = _T('0');
                  *pT++ = _T(' ');
               }
               // FALL THROUGH
            }
            if( State == STATE_INNERHTML ) {
               State = STATE_TAG;
               *pT++ = _T('\\');
               *pT++ = _T('b');
               *pT++ = _T(' ');
               *pT++ = ch;
               *pT++ = _T('\\');
               *pT++ = _T('b');
               *pT++ = _T('0');
               *pT++ = _T('\\');
               *pT++ = _T('c');
               *pT++ = _T('f');
               *pT++ = _T('1');
               *pT++ = _T(' ');
               if( _tcsnicmp( pstrText, _T("SCRIPT"), 6 )==0 ) bIsScript=true;
               if( _tcsnicmp( pstrText, _T("!--"), 3 )==0 ) {
                  State = STATE_COMMENT;
                  *pT++ = _T('\\');
                  *pT++ = _T('c');
                  *pT++ = _T('f');
                  *pT++ = _T('4');
                  *pT++ = _T(' ');
               };
            }
            else {
               *pT++ = ch;
            }
            break;
         case _T('>'):
            if( State==STATE_TAG || State==STATE_ATTRIB ) {
               State = STATE_INNERHTML;
               *pT++ = _T('\\');
               *pT++ = _T('c');
               *pT++ = _T('f');
               *pT++ = _T('0');
               *pT++ = _T('\\');
               *pT++ = _T('b');
               *pT++ = _T(' ');
               *pT++ = ch;
               *pT++ = _T('\\');
               *pT++ = _T('b');
               *pT++ = _T('0');
               if( bIsScript ) {
                  State = STATE_SCRIPT;
                  bIsScript=false;
                  *pT++ = _T('\\');
                  *pT++ = _T('c');
                  *pT++ = _T('f');
                  *pT++ = _T('3');
               };
               *pT++ = _T(' ');
            }
            else {
               *pT++ = ch;
            }
            break;
         case _T('\''):
         case _T('\"'):
            if( State == STATE_ATTRIB ) {
               chString = ch;
               State = STATE_STRING;
               *pT++ = ch;
               *pT++ = _T('\\');
               *pT++ = _T('I');
               *pT++ = _T(' ');
            }
            else if( State == STATE_STRING && ch==chString ) {
               State = STATE_ATTRIB;
               *pT++ = _T('\\');
               *pT++ = _T('I');
               *pT++ = _T('0');
               *pT++ = _T(' ');
               *pT++ = ch;
            }
            else {
               *pT++ = ch;
            }
            break;
         case _T('-'):
            if( State==STATE_COMMENT ) {
               if( _tcsncmp( pstrText, _T("->"), 2 )==0 ) State = STATE_TAG;
               *pT++ = ch;
            }
            else {
               *pT++ = ch;
            }
            break;
         case _T('\\'):
            *pT++ = _T('\\');
            *pT++ = _T('\\');
            break;
         case _T('{'):
            *pT++ = _T('\\');
            *pT++ = _T('{');
            break;
         case _T('}'):
            *pT++ = _T('\\');
            *pT++ = _T('}');
            break;
         case _T('\r'):
            break;
         case _T('='):
            if( State == STATE_ATTRIB ) {
               *pT++ = _T('\\');
               *pT++ = _T('c');
               *pT++ = _T('f');
               *pT++ = _T('5');
               *pT++ = _T(' ');
            }
            *pT++ = ch;
            break;
         case _T('\n'):
               *pT++ = _T('\\');
               *pT++ = _T('p');
               *pT++ = _T('a');
               *pT++ = _T('r');
               *pT++ = _T(' ');
               // fall through
         case _T('\t'):
         case _T(' '):
            if( State == STATE_TAG || State == STATE_ATTRIB ) {
               // NOTE: Return color back to light-red after TAG and
               //       after complete ATTRIB parse.
               State = STATE_ATTRIB;
               *pT++ = _T('\\');
               *pT++ = _T('c');
               *pT++ = _T('f');
               *pT++ = _T('2');
               *pT++ = _T(' ');
               // FALL THROUGH
            }
            // Parse away duplicate spaces/tabs
            *pT++ = ch;
            if( ch==_T('\t') || ch==_T(' ') ) {
               while( *pstrText && *pstrText==ch ) {
                  *pT++ = *pstrText++;
               };
            }
            break;
         default:
            *pT++ = ch;
            // Copy the complete word
            while( *pstrText && _istalnum(*pstrText) ) {
               *pT++ = *pstrText++;
            };
         }
         if( pT > pEnd ) break; // TODO: Add intelligent string growth
      };
      *pT = _T('\0');

      ATLTRACE("Text size after: %d\n", _tcslen(pstrTarget));
      s.ReleaseBuffer();
      return s;
   };

};


#endif // !defined(AFX_HTMLFORMAT_H__20000615_4D55_5A69_4ACA_0080AD509054__INCLUDED_)

